/////////////////////////////////////////////////////////////////////////////
//
// (c) 2007 BinaryComponents Ltd.  All Rights Reserved.
//
// http://www.binarycomponents.com/
//
/////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace SuperListEx.Sections
{
	public class RowSection : SectionContainer
    {
        #region vars
        private Color _ItemBackgroundColor;
        private Color _ItemForegroundColor;
        private Font _ItemFont;
        private const int _separatorLineHeight = 1;
        private readonly int _position;
        private readonly RowIdentifier _rowIdentifier;
        private readonly HeaderSection _headerSection;
        private bool _drawnSelected = false;
        #endregion

        #region properties
        public Color SeperatorColor
        {
            get;
            set;
        }

        public Color IndentColor
        {
            get;
            set;
        }

        public Font ItemFont
        {
            get
            {
                return (_ItemFont);
            }
        }

        public Color ItemBackgroundColor
        {
            get
            {
                return (_ItemBackgroundColor);
            }
        }

        public Color ItemForegroundColor
        {
            get
            {
                return (_ItemForegroundColor);
            }
        }

        protected virtual int IndentWidth
        {
            get
            {
                return Children.Count > 0 ? Children[0].Rectangle.X - Rectangle.X : 0;
            }
        }

        protected ListSection ListSection
        {
            get
            {
                return (ListSection)Parent;
            }
        }

        protected ListControl ListControl
        {
            get
            {
                return (ListControl)Host;
            }
        }

        public override bool CanDrag
        {
            get
            {
                return ListSection.AllowRowDragDrop;
            }
            set
            {
                ListSection.AllowRowDragDrop = value;
            }
        }

        public Object Item
        {
            get
            {
                return _rowIdentifier.Items[0];
            }
        }

        public int Position
        {
            get
            {
                return _position;
            }
        }

        public RowIdentifier RowIdentifier
        {
            get
            {
                return _rowIdentifier;
            }
        }

        public HeaderSection HeaderSection
        {
            get
            {
                return _headerSection;
            }
        }

        public bool DrawnSelected
        {
            get
            {
                return _drawnSelected;
            }
        }

        public virtual bool NeedsLayoutOnSelection
        {
            get
            {
                return false;
            }
        }

        public bool IsSelected
        {
            get
            {
                return ListSection.SelectedItems.IsSelected(RowIdentifier);
            }
        }

        public bool IsFocused
        {
            get
            {
                return ListSection.HasFocus(RowIdentifier);
            }
        }
        #endregion

        #region constructors
        public RowSection( ListControl listControl, RowIdentifier rowIdentifier, HeaderSection headerSection, int position )
			: base( listControl )
		{
            _ItemBackgroundColor = listControl.CustomBackgroundColorAccessor(rowIdentifier.Items[0]);
            _ItemForegroundColor = listControl.CustomForegroundColorAccessor(rowIdentifier.Items[0]);
            _ItemFont = listControl.CustomFontAccessor(rowIdentifier.Items[0]);
			_headerSection = headerSection;
			_rowIdentifier = rowIdentifier;
			_position = position;
			SeperatorColor = listControl.SeparatorColor;
			IndentColor = listControl.IndentColor;
        }
        #endregion

        #region public functions
        public override IEnumerable<Section> GetExpandedDragList()
		{
			List<Section> sections = new List<Section>();
			foreach( Section s in ListSection.Children )
			{
				RowSection rowSection = s as RowSection;
				if( rowSection != null && rowSection.IsSelected )
				{
					sections.Add( rowSection );
				}
			}
			return sections;
		}

		public override List<object> GetDragObjects()
		{
            return ListSection.SelectedItems.ToList().ConvertAll<object>(O => (object)O);
		}

		public override void DragLeave()
		{
			base.DragLeave();
			this.Invalidate();
		}

		public override void DraggingOver( Point pt, System.Windows.Forms.IDataObject dataObject )
		{
			this.Invalidate();
		}

		public override void Layout( GraphicsSettings gs, Size maximumSize )
		{
			DeleteChildren();

			int bottom = Location.Y;

			foreach( Section s in _headerSection.Children )
			{
				HeaderColumnSection hcs = s as HeaderColumnSection;

				if( hcs != null )
				{
					CellSection cellSection = Host.SectionFactory.CreateCellSection( Host, hcs, Item );

					Children.Add( cellSection );

					//
					//	We position the cell aligned to its corresponding HeaderColumnSection. We nudge it to right here
					//	based on any difference between the column size and the headers columns actual size. The only time there
					//	will be a different currently is when we have multiple groups reserving initial space on the first column.
					cellSection.Location = new Point( hcs.Location.X + hcs.Rectangle.Width - hcs.Column.Width, Location.Y );
					cellSection.Layout( gs, new Size( hcs.Column.Width, maximumSize.Height ) );
					bottom = Math.Max( bottom, cellSection.Rectangle.Bottom );
				}
			}
			int newHeigt = MinimumHeight;
			if( bottom - Rectangle.Top > MinimumHeight )
			{
				newHeigt = bottom - Rectangle.Top;
			}
			Size = new Size( HeaderSection.Rectangle.Width, newHeigt );
		}

		public void PaintSelection( GraphicsSettings gs )
		{
			//System.Diagnostics.Debug.WriteLine( this.Host.CurrentSectionDraggedOver );
			if( IsSelected )
			{
				gs.Graphics.FillRectangle( Host.FocusedSection == ListSection ? SystemBrushes.Highlight : SystemBrushes.ButtonFace, Rectangle );
			}

			else if( this.Host.CurrentSectionDraggedOver == this )
			{
				Color h = SystemColors.Highlight;
				Color c = Color.FromArgb( h.A / 3, h.R, h.G, h.B );
				using( SolidBrush brush = new SolidBrush( c ) )
				{
					gs.Graphics.FillRectangle( brush, Rectangle );
				}
			}

            else if (((ListControl) this.Host).CustomBackgroundColorAccessor != null && !(this is GroupSection))
            {
                gs.Graphics.FillRectangle(new SolidBrush(_ItemBackgroundColor), Rectangle);
            }

            else if (ListControl.AlternatingRowColor != Color.Empty && Position % 2 == 0 && RowIdentifier.GroupColumns.Count == 0)
            {
                gs.Graphics.FillRectangle(new SolidBrush(ListControl.AlternatingRowColor), Rectangle);
            }
		}

		public override void PaintBackground( GraphicsSettings gs, Rectangle clipRect )
		{
			PaintSelection( gs );
			_drawnSelected = IsSelected;

			if( IsFocused )
			{
				Rectangle rc = HostBasedRectangle;
				int indent = IndentWidth;
				Rectangle focusRect = new Rectangle( rc.X + indent, rc.Y, rc.Width - indent, Rectangle.Height );

				focusRect.Width -= 1;
				if( this is GroupSection )
				{
					focusRect.Height -= _separatorLineHeight;
				}
				focusRect.Height -= 2;

				using( Pen pen = new Pen( SystemColors.ControlDark ) )
				{
					pen.DashStyle = DashStyle.Dot;
					gs.Graphics.DrawRectangle( pen, focusRect );
				}
			}
		}

		protected virtual void PaintSeparatorLine( Graphics g, Rectangle rc )
		{
			using( Pen pen = new Pen( Color.FromArgb( 70, SeperatorColor.R, SeperatorColor.G, SeperatorColor.B ), _separatorLineHeight ) )
			{
				g.DrawLine( pen, new Point( rc.Left, rc.Bottom - _separatorLineHeight ), new Point( rc.Right, rc.Bottom - _separatorLineHeight ) );
			}
		}

		public override void Paint( GraphicsSettings gs, Rectangle clipRect )
		{
			//
			// Fill indent area
			if( Children.Count > 0 )
			{
				Rectangle rc = HostBasedRectangle;
				Rectangle rcIndent = new Rectangle( rc.X, Rectangle.Y, Children[0].HostBasedRectangle.X - rc.X, rc.Height );

				PaintIndentArea( gs.Graphics, rcIndent );
			}

			base.Paint( gs, clipRect );

			Rectangle rcLine = Rectangle;
			rcLine.X += IndentWidth;
			PaintSeparatorLine( gs.Graphics, rcLine );
		}

		protected virtual void PaintIndentArea( Graphics g, Rectangle rcIndent )
		{
		}

		public CellSection CellSectionFromPoint( Point pt )
		{
			pt.X += GetAbsoluteScrollCoordinates().X;
			pt.Y += GetAbsoluteScrollCoordinates().Y;
			foreach( Section s in Children )
			{
				CellSection cs = s as CellSection;
				if( cs != null )
				{
					Section sectionFromPoint = cs.SectionFromPoint( pt );
					if( sectionFromPoint != null )
					{
						return cs;
					}
				}
			}
			return null;
        }
        #endregion
    }
}